package cn.com.surker.production.service.impl;

import cn.com.surker.enums.StateEnum;
import cn.com.surker.enums.production.invoice.InvoiceCreateTypeEnum;
import cn.com.surker.enums.production.invoice.InvoiceProcessEnum;
import cn.com.surker.production.dao.InvoiceHandleDao;
import cn.com.surker.production.dao.ProductionInvoiceDao;
import cn.com.surker.production.entity.ProductionIndent;
import cn.com.surker.production.entity.ProductionInvoice;
import cn.com.surker.production.entity.report.ProductionInvoiceReport;
import cn.com.surker.production.entity.vo.ProductionInvoiceVo;
import cn.com.surker.production.service.ProductionInvoiceService;
import cn.com.surker.util.MathUtils;
import cn.com.surker.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.cache.annotation.Cacheable;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 生产发货单表 服务实现类
 * </p>
 *
 * @author admin
 * @since 2024-07-25
 */
public abstract class ProductionInvoiceBaseImpl extends ServiceImpl<ProductionInvoiceDao, ProductionInvoice> implements ProductionInvoiceService {

	@Resource
	protected ProductionInvoiceDao invoiceDao;

	@Override
	public IPage<ProductionInvoiceVo> selectFullPage(String erpDb, String startDate, String endDate, String searchVal, String searchVal2,Long conId, Long indentId,
													 Integer createType, Integer process, Integer isAdd, Integer isLinked, Integer pageIndex, Integer limit) {
		QueryWrapper<ProductionInvoice> qw = initFullParam(startDate, endDate, searchVal, searchVal2,conId, indentId, createType, process, isAdd, isLinked);
		PageHelper.startPage(pageIndex, limit);
		Page<ProductionInvoiceVo> iPage = invoiceDao.selectFull(erpDb, new Page<>((pageIndex + limit) / limit, limit), qw);
		/**分页插件**/
		if (!StringUtils.isNull(iPage.getRecords())) {
			PageInfo pageInfo = new PageInfo(iPage.getRecords());
			if (!StringUtils.isNull(pageInfo.getTotal()))
				iPage.setTotal(pageInfo.getTotal());
		}
		return iPage;
	}

	@Override
	public IPage<ProductionInvoiceVo> selectFullPageV2(String erpDb, String startDate, String endDate, String searchVal, Long conId, Long indentId,
													   Integer createType, List<Integer> processList, Integer pageIndex, Integer limit) {
		QueryWrapper<ProductionInvoice> qw = initFullParamV2(startDate, endDate, searchVal, conId, indentId, createType, processList);
		PageHelper.startPage(pageIndex, limit);
		Page<ProductionInvoiceVo> iPage = invoiceDao.selectFull(erpDb, new Page<>((pageIndex + limit) / limit, limit), qw);
		/**分页插件**/
		if (!StringUtils.isNull(iPage.getRecords())) {
			PageInfo pageInfo = new PageInfo(iPage.getRecords());
			if (!StringUtils.isNull(pageInfo.getTotal()))
				iPage.setTotal(pageInfo.getTotal());
		}
		return iPage;
	}

	@Override
	public List<ProductionInvoiceVo> selectFullList(String erpDb, String startDate, String endDate, String searchVal, String searchVal2,Long conId, Long indentId,
													Integer createType, Integer process, Integer isAdd) {
		QueryWrapper<ProductionInvoice> qw = initFullParam(startDate, endDate, searchVal,searchVal2, conId, indentId, createType, process, isAdd, null);
		List<ProductionInvoiceVo> invoiceVoList = invoiceDao.selectFull(erpDb, qw);
		return invoiceVoList;
	}

	/**
	 * 初始化查询完整信息的参数
	 *
	 * @param startDate        起始时间
	 * @param endDate        截止时间
	 * @param searchVal        合同名称
	 * @param createType        生产方式
	 * @param process        发货单生产状态
	 * @return
	 */
	protected QueryWrapper<ProductionInvoice> initFullParam(String startDate, String endDate, String searchVal, String searchVal2,Long conId, Long indentId,
															Integer createType, Integer process, Integer isAdd, Integer isLinked) {
		QueryWrapper<ProductionInvoice> qw = new QueryWrapper<>();
		qw.eq("a.status", StateEnum.ENABLED.getCode());
		if (StringUtils.isNotBlank(startDate)) {
			qw.ge("a.pro_time", startDate);
		}
		if (StringUtils.isNotBlank(endDate)) {
			qw.lt("a.pro_time", endDate);
		}
		if (StringUtils.isNotBlank(searchVal)) {
			qw.and(e -> {
				e.like("indent.code", searchVal).or().like("a.code", searchVal).or().like("con.name", searchVal).or().like("indent.site", searchVal)
					.or().like("strength.strength", searchVal)
					.or().inSql("a.car_id", "SELECT tran_car_id from production_tran_con_car WHERE CODE like '%" + searchVal + "%' and org_id = a.org_id and status = 0" +
					" and (start_time < a.pro_time or start_time < a.create_time)");
			});
			if (StringUtils.isNotBlank(searchVal2)){
				qw.and(e -> {
					e.like("indent.code", searchVal2).or().like("a.code", searchVal2).or().like("con.name", searchVal2).or().like("indent.site", searchVal2)
						.or().like("strength.strength",searchVal2)
						.or().inSql("a.car_id", "SELECT tran_car_id from production_tran_con_car WHERE CODE like '%" + searchVal2 + "%' and org_id = a.org_id and status = 0" +
						" and (start_time < a.pro_time or start_time < a.create_time)");
				});
			}
		}
		if (createType != null) {
			if (createType != InvoiceCreateTypeEnum.MOVEMENT.getCode()) {
				qw.eq("a.create_type", createType);
			} else {
				//	如果是手动票,则要取出工控机生产中断的数据
				qw.and(e -> {
					e.eq("a.create_type", InvoiceCreateTypeEnum.MOVEMENT.getCode()).or().eq("a.process", InvoiceProcessEnum.WORK_ORDER_1.getCode());
				});
			}
		}
		if (isLinked != null) {
			if (isLinked == 1) {
				// 手动票关联的erp
				qw.isNotNull("control_invoice_id");
			} else {
				// 未关联
				qw.isNull("control_invoice_id");
			}
		}
		if (conId != null) {
			qw.eq("con.id", conId);
		}
		if (indentId != null) {
			qw.eq("indent.id", indentId);
		}
		if (process != null) {
			qw.eq("a.process", process);
		}
		if (isAdd != null && isAdd > -1) {
			if (isAdd.equals(0)) {
				//	需要累计
				qw.and(e -> {
					e.isNull("a.is_add").or().eq("a.is_add", 0);
				});
			} else {
				//	不累计
				qw.eq("a.is_add", isAdd);
			}
		}
		/*else {
			qw.notIn("a.process", InvoiceProcessEnum.QUERN_FAIL.getCode(),InvoiceProcessEnum.WAIT_DEL.getCode(),InvoiceProcessEnum.DEL.getCode());
		}*/
		qw.orderByDesc("a.pro_time");
		return qw;
	}

	protected QueryWrapper<ProductionInvoice> initFullParamV2(String startDate, String endDate, String searchVal, Long conId, Long indentId,
															  Integer createType, List<Integer> processList) {
		QueryWrapper<ProductionInvoice> qw = new QueryWrapper<>();
		qw.eq("a.status", StateEnum.ENABLED.getCode());
		if (StringUtils.isNotBlank(startDate)) {
			qw.ge("a.pro_time", startDate);
		}
		if (StringUtils.isNotBlank(endDate)) {
			qw.ge("a.pro_time", endDate);
		}
		if (StringUtils.isNotBlank(searchVal)) {
			qw.and(e -> {
				e.like("indent.code", searchVal).or().like("a.code", searchVal).or().like("con.name", searchVal).or().like("indent.site", searchVal);
			});
		}
		if (conId != null) {
			qw.eq("con.id", conId);
		}
		if (indentId != null) {
			qw.eq("indent.id", indentId);
		}
		if (createType != null) {
			qw.eq("a.create_type", createType);
		}
		if (processList != null && processList.size() > 0) {
			qw.in("a.process", processList);
		}
		qw.orderByDesc("a.pro_time");
		return qw;
	}


	@Override
	public ProductionInvoiceVo queryOverview(String erpDb, Long orgId, Long id) {
		if (id == null) {
			return null;
		}
		ProductionInvoiceVo inv = invoiceDao.queryOverview(erpDb, id);
		return inv;
	}

	@Override
	public ProductionInvoiceVo queryDetail(String erpDb, Long orgId, Long id) {
		//	查询发货单总览信息
		QueryWrapper<ProductionInvoice> qw = new QueryWrapper<>();
		qw.eq("a.id", id);
		List<ProductionInvoiceVo> invList = invoiceDao.invoiceDetail(erpDb, qw);
		if (invList == null || invList.isEmpty()) {
			return null;
		}
		ProductionInvoiceVo invoiceVo = invList.get(0);
		return invoiceVo;
	}

	@Override
	public List<ProductionInvoice> findByIndent(String orgDb, Long indentId) {
		if (indentId == null) {
			return null;
		}
		List<ProductionInvoice> list = invoiceDao.findByIndent(orgDb, indentId);
		return list;
	}

	@Override
	public List<ProductionInvoiceVo> findList(String orgDb, String startTime, String endTime) {
		if (StringUtils.isBlank(orgDb)) {
			return null;
		}
		List<ProductionInvoiceVo> list = invoiceDao.findList(orgDb, startTime, endTime);
		return list;
	}

	/*@Override
	public UpdateChainWrapper<ProductionInvoice> update() {
		return null;
	}*/

	@Override
	public Double queryTranStere(Long invoiceId) {
		ProductionInvoiceVo invoiceVo = invoiceDao.queryTranStere(invoiceId);
		if (invoiceVo == null) {
			return 0d;
		}
		Double inStere = invoiceVo.getInStere();
		Double outStere = invoiceVo.getOutStere();
		Double proStere = invoiceVo.getProStere();
		//	运输方量为生产方量+转入方量-转出方量
		Double tranStere = MathUtils.add(inStere, proStere);
		tranStere = MathUtils.subtract(tranStere, outStere);
		return tranStere;
	}

	/**
	 * 开盘鉴定汇总
	 * @param dbCode
	 * @param searchVal
	 * @param startTime
	 * @param endTime
	 * @return
	 */
	public ProductionInvoiceReport findLabIndentSum(String dbCode, String searchVal, String startTime, String endTime) {
		if (StringUtils.isNull(startTime))
			startTime = null;
		if (StringUtils.isNull(endTime))
			endTime = null;
		QueryWrapper<ProductionIndent> query = new QueryWrapper<>();
		query.eq("inv.status", 0);
		if (StringUtils.isNotBlank(startTime)) {
			query.ge("inv.pro_time", startTime);
		}
		if (StringUtils.isNotBlank(endTime)) {
			query.lt("inv.pro_time", endTime);
		}
		query.inSql("inv.indent_id", "select id from " + dbCode + ".production_indent where status = 0 \n" +
				"and (site like '%" + searchVal + "%' or code like '%" + searchVal + "%' \n" +
				"or remark like '%" + searchVal + "%' or con_id in (select id from " + dbCode + ".sale_contract \n" +
				"where status = 0 and (name like '%" + searchVal + "%') or receipt_unit like '%" + searchVal + "%'))");
		ProductionInvoiceReport invoiceReport = invoiceDao.findLabIndentSum(dbCode, startTime, endTime, query);
		return invoiceReport;
	}

	/**
	 * 技术部开盘鉴定台账
	 * @param dbCode
	 * @return
	 */
	public IPage<ProductionInvoiceReport> findLabIndentReport(String dbCode, String searchVal, String startTime, String endTime, Integer offset, Integer limit) {
		if (StringUtils.isNull(startTime))
			startTime = null;
		if (StringUtils.isNull(endTime))
			endTime = null;
		PageHelper.offsetPage(offset, limit);
		QueryWrapper<ProductionIndent> query = new QueryWrapper<>();
		query.eq("a.status", StateEnum.ENABLED.getCode());
		query.gt("invStereT.proStere", 0);
		if (StringUtils.isNotBlank(searchVal)) {
			query.and(orderWrapper -> orderWrapper.like("a.site", searchVal).or()
					.like("a.code", searchVal).or().like("c.name", searchVal).or()
					.like("b.name", searchVal).or().like("d.name", searchVal)
					.or().like("a.remark", searchVal).or().like("b.receipt_unit", searchVal)
					.or().like("f.strength", searchVal));
		}
		query.groupBy("a.id");
		query.orderByAsc("invStereT.pro_time");
		IPage<ProductionInvoiceReport> iPage = invoiceDao.findLabIndentReport(new Page<>((offset + limit) /limit, limit),
				dbCode, startTime, endTime, query);
		/**分页插件**/
		if (!StringUtils.isNull(iPage.getRecords())) {
			PageInfo pageInfo = new PageInfo(iPage.getRecords());
			if (!StringUtils.isNull(pageInfo.getTotal()))
				iPage.setTotal(pageInfo.getTotal());
		}
		return iPage;
	}
	/**
	 * 分页查询任务单台账
	 * @param dbCode
	 * @return
	 */
	public IPage<ProductionInvoiceReport> findIndentReport(String dbCode, String searchVal, String startTime, String endTime,
													Integer proType, Integer offset, Integer limit) {
		if (StringUtils.isNull(startTime))
			startTime = null;
		if (StringUtils.isNull(endTime))
			endTime = null;
		PageHelper.offsetPage(offset, limit);
		QueryWrapper<ProductionIndent> query = new QueryWrapper<>();
		query.eq("a.status", StateEnum.ENABLED.getCode());
		query.gt("invStereT.proStere", 0);
		if (StringUtils.isNotBlank(searchVal)) {
			query.and(orderWrapper -> orderWrapper.like("a.site", searchVal).or()
					.like("a.code", searchVal).or().like("c.name", searchVal).or()
					.like("b.name", searchVal).or().like("d.name", searchVal)
					.or().like("a.remark", searchVal).or().like("b.receipt_unit", searchVal)
					.or().like("f.strength", searchVal));
		}
		if (!StringUtils.isNull(proType))
			query.eq("a.type", proType);
		query.groupBy("a.id");
		query.orderByDesc("invStereT.pro_time");
		IPage<ProductionInvoiceReport> iPage = invoiceDao.findLabIndentReport(new Page<>((offset + limit) /limit, limit),
				dbCode, startTime, endTime, query);
		/**分页插件**/
		if (!StringUtils.isNull(iPage.getRecords())) {
			PageInfo pageInfo = new PageInfo(iPage.getRecords());
			if (!StringUtils.isNull(pageInfo.getTotal()))
				iPage.setTotal(pageInfo.getTotal());
		}
		return iPage;
	}
	/**
	 * 任务单详情
	 * @param dbCode
	 * @param indentId
	 * @return
	 */
	public ProductionInvoiceReport findIndentDetail(String dbCode, Long indentId) {
		if (StringUtils.isAllParamNull(dbCode, indentId))
			return null;
		QueryWrapper<ProductionIndent> query = new QueryWrapper<>();
		query.eq("a.status", StateEnum.ENABLED.getCode());
		query.eq("a.id", indentId);
		query.groupBy("a.id");
		List<ProductionInvoiceReport> invoiceReportList = invoiceDao.findLabIndentReport(dbCode, null, null, query);
		if (invoiceReportList == null || invoiceReportList.size() == 0)
			return null;
		ProductionInvoiceReport invoiceReport = invoiceReportList.get(0);
		QueryWrapper<ProductionInvoice> qw = new QueryWrapper<>();
		qw.eq("a.status", StateEnum.ENABLED.getCode());
		qw.eq("indent.id", indentId);
		qw.orderByDesc("a.pro_time");
		List<ProductionInvoiceVo> invoiceVoList = invoiceDao.selectFull(dbCode, qw);
		invoiceReport.setInvoiceList(invoiceVoList);
		return invoiceReport;
	}
	/**
	 *
	 * @param dbCode
	 * @return
	 */
	public ProductionInvoiceReport findIndentSum(String dbCode, String searchVal, String startTime, String endTime, Integer proType) {
		if (StringUtils.isNull(startTime))
			startTime = null;
		if (StringUtils.isNull(endTime))
			endTime = null;
		QueryWrapper<ProductionIndent> query = new QueryWrapper<>();
		query.eq("inv.status", 0);
		if (StringUtils.isNotBlank(startTime)) {
			query.ge("inv.pro_time", startTime);
		}
		if (StringUtils.isNotBlank(endTime)) {
			query.lt("inv.pro_time", endTime);
		}
		String sql = "select id from " + dbCode + ".production_indent where status = 0 \n" +
				"and (site like '%" + searchVal + "%' or code like '%" + searchVal + "%' \n" +
				"or remark like '%" + searchVal + "%' or con_id in (select id from " + dbCode + ".sale_contract \n" +
				"where status = 0 and (name like '%" + searchVal + "%') or receipt_unit like '%" + searchVal + "%')) ";
		if (!StringUtils.isNull(proType))
			sql += " and type = " + proType;
		query.inSql("inv.indent_id", sql);
		ProductionInvoiceReport invoiceReport = invoiceDao.findLabIndentSum(dbCode, startTime, endTime, query);
		return invoiceReport;
	}
	/**
	 * 导出技术部开盘鉴定台账数据
	 * @param dbCode
	 * @return
	 */
	public List<ProductionInvoiceReport> findLabIndentReport(String dbCode, String searchVal, String startTime, String endTime){
		QueryWrapper<ProductionIndent> query = new QueryWrapper<>();
		query.eq("a.status", StateEnum.ENABLED.getCode());
		query.gt("invStereT.proStere", 0);
		if (StringUtils.isNotBlank(searchVal)) {
			query.and(orderWrapper -> orderWrapper.like("a.site", searchVal).or()
					.like("a.code", searchVal).or().like("c.name", searchVal).or()
					.like("b.name", searchVal).or().like("d.name", searchVal)
					.or().like("a.remark", searchVal).or().like("b.receipt_unit", searchVal)
					.or().like("f.strength", searchVal));
		}
		query.groupBy("a.id");
		query.orderByAsc("invStereT.pro_time");
		List<ProductionInvoiceReport> list = invoiceDao.findLabIndentReport(dbCode, startTime, endTime, query);
		if (list == null || list.size() == 0)
			return null;
		return list;
	}

	@Override
	public Double queryConSendStere(String dbCode, Long conId) {
		Double conSendStere = invoiceDao.queryConSendStere(dbCode, conId);
		return conSendStere;
	}

	@Override
	public Double queryConBakStere(String dbCode, Long conId) {
		Double conbakStere = invoiceDao.queryConBakStere(dbCode, conId);
		return conbakStere;
	}

	@Override
	public Double queryProStere(String dbCode, Long invoiceId) {
		Double proStere = invoiceDao.queryProStere(dbCode, invoiceId);
		if (proStere == null) {
			proStere = invoiceDao.queryControlStere(dbCode, invoiceId);
		}
		return proStere;
	}

	@Override
	public Map<String, Object> queryTotalStere(String dbCode, Long indentId) {
		if (StringUtils.isBlank(dbCode) || indentId == null) {
			return null;
		}
		Map<String, Object> res = invoiceDao.queryTotalStere(dbCode, indentId);
		return res;
	}

	@Override
	public List<String> findTranCar(String dbCode, Long indentId) {
		if (StringUtils.isBlank(dbCode) || indentId == null) {
			return null;
		}
		List<String> tranCar = invoiceDao.findTranCar(dbCode, indentId);
		return tranCar;
	}


	@Override
	protected Class<ProductionInvoice> currentModelClass() {
		return ProductionInvoice.class;
	}
}